"""
GT-LMS系统的用户管理器
此模块实现用户管理器，采用单例模式管理用户数据
"""

from typing import Dict, List, Optional, Any
from datetime import datetime
import json
import os
from pathlib import Path
import sys

# 添加项目根目录到Python路径
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

from models.user import User, Student, Teacher, Admin, UserRole


class UserManager:
    """用户管理器 - 采用单例模式"""
    
    _instance = None
    _initialized = False
    
    def __new__(cls):
        """单例模式实现"""
        if cls._instance is None:
            cls._instance = super(UserManager, cls).__new__(cls)
        return cls._instance
    
    def __init__(self):
        """初始化用户管理器"""
        if self._initialized:
            return
        
        self.users: Dict[str, User] = {}  # user_id -> User对象
        self.email_to_user_id: Dict[str, str] = {}  # email -> user_id
        self.role_users: Dict[UserRole, List[str]] = {
            UserRole.STUDENT: [],
            UserRole.TEACHER: [],
            UserRole.ADMIN: []
        }
        self.data_file = "users.json"
        self._initialized = True
        self.load_users()
    
    def create_user(self, user_type: str, user_data: Dict[str, Any]) -> Optional[User]:
        """
        创建用户
        
        参数:
            user_type: 用户类型 ('student', 'teacher', 'admin')
            user_data: 用户数据字典
            
        返回:
            创建的用户对象，失败返回None
        """
        try:
            user_id = user_data.get('user_id')
            name = user_data.get('name')
            email = user_data.get('email')
            password = user_data.get('password')
            
            if not all([user_id, name, email, password]):
                print("错误：缺少必要的用户信息")
                return None
            
            # 检查用户ID是否已存在
            if user_id in self.users:
                print(f"错误：用户ID '{user_id}' 已存在")
                return None
            
            # 检查邮箱是否已存在
            if email in self.email_to_user_id:
                print(f"错误：邮箱 '{email}' 已被使用")
                return None
            
            # 根据用户类型创建相应的用户对象
            if user_type == 'student':
                student_number = user_data.get('student_number', user_id)
                major = user_data.get('major', '')
                enrollment_year = user_data.get('enrollment_year')
                
                user = Student(
                    user_id=user_id,
                    name=name,
                    email=email,
                    password=password,
                    student_number=student_number,
                    major=major,
                    enrollment_year=enrollment_year
                )
                
            elif user_type == 'teacher':
                employee_id = user_data.get('employee_id', user_id)
                department = user_data.get('department', '')
                office_hours = user_data.get('office_hours', '')
                
                user = Teacher(
                    user_id=user_id,
                    name=name,
                    email=email,
                    password=password,
                    employee_id=employee_id,
                    department=department,
                    office_hours=office_hours
                )
                
            elif user_type == 'admin':
                admin_level = user_data.get('admin_level', 1)
                
                user = Admin(
                    user_id=user_id,
                    name=name,
                    email=email,
                    password=password,
                    admin_level=admin_level
                )
            else:
                print(f"错误：未知的用户类型 '{user_type}'")
                return None
            
            # 添加用户到管理器
            self.users[user_id] = user
            self.email_to_user_id[email] = user_id
            self.role_users[user.role].append(user_id)
            
            # 保存用户数据
            self.save_users()
            
            print(f"成功创建用户：{name} ({user_type})")
            return user
            
        except Exception as e:
            print(f"创建用户时出错：{e}")
            return None
    
    def get_user(self, user_id: str) -> Optional[User]:
        """
        通过用户ID获取用户对象
        
        参数:
            user_id: 用户ID
            
        返回:
            用户对象，如果未找到则返回None
        """
        return self.users.get(user_id)
    
    def get_user_by_email(self, email: str) -> Optional[User]:
        """
        通过邮箱获取用户对象
        
        参数:
            email: 用户邮箱
            
        返回:
            用户对象，如果未找到则返回None
        """
        user_id = self.email_to_user_id.get(email)
        if user_id:
            return self.users.get(user_id)
        return None
    
    def update_user(self, user_id: str, update_info: Dict[str, Any]) -> bool:
        """
        更新用户信息
        
        参数:
            user_id: 用户ID
            update_info: 更新信息字典
            
        返回:
            更新是否成功
        """
        user = self.get_user(user_id)
        if not user:
            print(f"用户未找到: {user_id}")
            return False
            
        try:
            # 更新通用字段
            allowed_fields = ['name', 'email']
            for field in allowed_fields:
                if field in update_info:
                    setattr(user, field, update_info[field])
            
            # 更新角色特定字段
            if isinstance(user, Student):
                student_fields = ['student_number', 'major', 'enrollment_year']
                for field in student_fields:
                    if field in update_info:
                        setattr(user, field, update_info[field])
                        
            elif isinstance(user, Teacher):
                teacher_fields = ['employee_id', 'department', 'office_hours']
                for field in teacher_fields:
                    if field in update_info:
                        setattr(user, field, update_info[field])
                        
            elif isinstance(user, Admin):
                admin_fields = ['admin_level']
                for field in admin_fields:
                    if field in update_info:
                        setattr(user, field, update_info[field])
            
            # 如果邮箱更新，更新邮箱映射
            if 'email' in update_info:
                # 删除旧的邮箱映射
                old_email = None
                for email, uid in self.email_to_user_id.items():
                    if uid == user_id:
                        old_email = email
                        break
                
                if old_email:
                    del self.email_to_user_id[old_email]
                
                # 添加新的邮箱映射
                self.email_to_user_id[update_info['email']] = user_id
            
            # 保存用户数据
            self.save_users()
            
            print(f"成功更新用户: {user_id}")
            return True
            
        except Exception as e:
            print(f"更新用户时出错: {e}")
            return False
    
    def delete_user(self, user_id: str) -> bool:
        """
        删除用户
        
        参数:
            user_id: 用户ID
            
        返回:
            删除是否成功
        """
        user = self.get_user(user_id)
        if not user:
            print(f"用户未找到: {user_id}")
            return False
            
        try:
            # 从用户字典中删除
            del self.users[user_id]
            
            # 从邮箱映射中删除
            email_to_delete = None
            for email, uid in self.email_to_user_id.items():
                if uid == user_id:
                    email_to_delete = email
                    break
            
            if email_to_delete:
                del self.email_to_user_id[email_to_delete]
            
            # 从角色用户列表中删除
            self.role_users[user.role].remove(user_id)
            
            # 保存用户数据
            self.save_users()
            
            print(f"成功删除用户: {user_id}")
            return True
            
        except Exception as e:
            print(f"删除用户时出错: {e}")
            return False
    
    def authenticate_user(self, email: str, password: str) -> Optional[User]:
        """
        验证用户凭据
        
        参数:
            email: 用户邮箱
            password: 用户密码
            
        返回:
            验证成功返回用户对象，失败返回None
        """
        user = self.get_user_by_email(email)
        if user and user.verify_password(password):
            return user
        return None
    
    def get_users_by_role(self, role: UserRole) -> List[User]:
        """
        获取指定角色的所有用户
        
        参数:
            role: 用户角色
            
        返回:
            用户列表
        """
        user_ids = self.role_users.get(role, [])
        return [self.users.get(user_id) for user_id in user_ids if user_id in self.users]
    
    def search_users(self, keyword: str) -> List[User]:
        """
        通过关键字搜索用户
        
        参数:
            keyword: 搜索关键字
            
        返回:
            匹配的用户列表
        """
        keyword = keyword.lower()
        results = []
        
        for user in self.users.values():
            # 搜索用户ID、姓名、邮箱
            if (keyword in user.user_id.lower() or 
                keyword in user.name.lower() or 
                keyword in user.email.lower()):
                results.append(user)
                continue
            
            # 搜索角色特定字段
            if isinstance(user, Student):
                if (keyword in user.student_number.lower() or 
                    keyword in user.major.lower()):
                    results.append(user)
                    
            elif isinstance(user, Teacher):
                if (keyword in user.employee_id.lower() or 
                    keyword in user.department.lower()):
                    results.append(user)
        
        return results
    
    def get_user_count(self) -> Dict[str, int]:
        """
        获取用户统计信息
        
        返回:
            用户统计字典
        """
        return {
            'total': len(self.users),
            'students': len(self.role_users[UserRole.STUDENT]),
            'teachers': len(self.role_users[UserRole.TEACHER]),
            'admins': len(self.role_users[UserRole.ADMIN]),
            'active': sum(1 for user in self.users.values() if user.is_active),
            'inactive': sum(1 for user in self.users.values() if not user.is_active)
        }
    
    def save_users(self) -> bool:
        """
        保存用户数据到文件
        
        返回:
            保存是否成功
        """
        try:
            data = {
                'users': {},
                'email_to_user_id': self.email_to_user_id,
                'role_users': {
                    role.value: user_ids for role, user_ids in self.role_users.items()
                },
                'last_updated': datetime.now().isoformat()
            }
            
            # 序列化用户数据
            for user_id, user in self.users.items():
                user_data = user.get_info()
                user_data['password'] = user._password  # 包含密码用于验证
                
                # 添加特定类型的额外数据
                if isinstance(user, Student):
                    user_data.update({
                        'student_number': user.student_number,
                        'major': user.major,
                        'enrollment_year': user.enrollment_year,
                        'enrolled_courses': user.enrolled_courses,
                        'gpa': user.gpa,
                        'grades': user.grades,
                        'user_type': 'student'
                    })
                elif isinstance(user, Teacher):
                    user_data.update({
                        'employee_id': user.employee_id,
                        'department': user.department,
                        'office_hours': user.office_hours,
                        'teaching_courses': user.teaching_courses,
                        'user_type': 'teacher'
                    })
                elif isinstance(user, Admin):
                    user_data.update({
                        'admin_level': user.admin_level,
                        'permissions': user.permissions,
                        'user_type': 'admin'
                    })
                
                data['users'][user_id] = user_data
            
            # 保存到文件
            with open(self.data_file, 'w', encoding='utf-8') as f:
                json.dump(data, f, indent=2, ensure_ascii=False)
            
            print(f"用户数据已保存到 {self.data_file}")
            return True
            
        except Exception as e:
            print(f"保存用户数据时出错：{e}")
            return False
    
    def load_users(self) -> bool:
        """
        从文件加载用户数据
        
        返回:
            加载是否成功
        """
        try:
            if not os.path.exists(self.data_file):
                print("用户数据文件不存在，将创建新文件")
                return True
            
            with open(self.data_file, 'r', encoding='utf-8') as f:
                data = json.load(f)
            
            # 清空现有数据
            self.users.clear()
            self.email_to_user_id.clear()
            for role_list in self.role_users.values():
                role_list.clear()
            
            # 恢复邮箱映射
            self.email_to_user_id = data.get('email_to_user_id', {})
            
            # 恢复角色用户映射
            role_users_data = data.get('role_users', {})
            for role_value, user_ids in role_users_data.items():
                role = UserRole(role_value)
                self.role_users[role] = user_ids
            
            # 重建用户对象
            users_data = data.get('users', {})
            for user_id, user_data in users_data.items():
                user_type = user_data.get('user_type')
                
                if user_type == 'student':
                    user = Student(
                        user_id=user_id,
                        name=user_data['name'],
                        email=user_data['email'],
                        password=user_data['password'],
                        student_number=user_data.get('student_number', user_id),
                        major=user_data.get('major', ''),
                        enrollment_year=user_data.get('enrollment_year', datetime.now().year)
                    )
                    user.enrolled_courses = user_data.get('enrolled_courses', [])
                    user.gpa = user_data.get('gpa', 0.0)
                    user.grades = user_data.get('grades', {})
                    
                elif user_type == 'teacher':
                    user = Teacher(
                        user_id=user_id,
                        name=user_data['name'],
                        email=user_data['email'],
                        password=user_data['password'],
                        employee_id=user_data.get('employee_id', user_id),
                        department=user_data.get('department', ''),
                        office_hours=user_data.get('office_hours', '')
                    )
                    user.teaching_courses = user_data.get('teaching_courses', [])
                    
                elif user_type == 'admin':
                    user = Admin(
                        user_id=user_id,
                        name=user_data['name'],
                        email=user_data['email'],
                        password=user_data['password'],
                        admin_level=user_data.get('admin_level', 1)
                    )
                else:
                    continue
                
                # 设置通用属性
                user.created_at = datetime.fromisoformat(user_data.get('created_at', datetime.now().isoformat()))
                user.last_login = datetime.fromisoformat(user_data.get('last_login', datetime.now().isoformat()))
                user.is_active = user_data.get('is_active', True)
                
                self.users[user_id] = user
            
            print(f"成功加载 {len(self.users)} 个用户")
            return True
            
        except Exception as e:
            print(f"加载用户数据时出错：{e}")
            return False
    
    def __str__(self) -> str:
        """字符串表示"""
        stats = self.get_user_count()
        return f"用户管理器 (总用户数: {stats['total']}, 学生: {stats['students']}, 教师: {stats['teachers']}, 管理员: {stats['admins']})"
    
    def __repr__(self) -> str:
        """详细表示"""
        return self.__str__()
    
    @classmethod
    def get_instance(cls):
        """获取UserManager单例实例"""
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance